package myJs.user

import myJs.Implicits.{JDJAn, _}
import myJs.myPkg.ResizableOptions
import myJs.myPkg.jquery.{$, JQuery}
import myJs.myPkg.topology._
import myJs.tool.Tool
import myJs.user.workflow.featureSelection._
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.{Element, Event}
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._
import scalatags.Text.all._
import scalax.collection.Graph
import scalax.collection.GraphPredef._
import shared.Pojo._
import shared.SharedTool
import shared.pojo.WorkflowMission.FsData
import upickle.default._

import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSON

/**
 * Created by yz on 2/12/2020
 */
trait FeatureSelectionTool{

  def getOtherNodes(topology: Topology) = {
    val pens = topology.data.pens
    val nodes = pens.filter { pen =>
      pen.`type` == PenType.Node && pen.id != "dataFileNode"
    }.map { pen =>
      pen.toNode
    }
    nodes.filterNot { node =>
      isInterUnionNode(node.id)
    }
  }

  def getCurSoft(idStr: String) = {
    val kind = SharedTool.getKind(idStr)
    AllFSSoft.kindSoftMap(kind)
  }

  def isInterUnionNode(idStr: String) = {
    idStr.startsWith("intersect") || idStr.startsWith("union")
  }

  def leftDrag: js.Function = (e: Event, y: Element, newWidth: Double, newHeight: Double, opt: ResizableOptions) => {
    val rowWidth = $(y).parents(".row").css("width").px2Double
    val minWidth = rowWidth * 0.08
    val maxWidth = rowWidth * 0.2
    if (newWidth <= minWidth || newWidth >= maxWidth) {
      false
    } else {
      val centerWidth = rowWidth * 0.99 - $("#right").width() - newWidth
      $("#center").width(centerWidth)
      true
    }
  }

  def addPen2ActiveLayer(topology: Topology, pen: Pen) = {
    topology.activeLayer.clear()
    topology.activeLayer.add(pen)
  }

  def getGraph(topology: Topology) = {
    val pens = topology.data.pens
    val lines = pens.filter { pen =>
      pen.`type` == PenType.Line
    }.map { pen =>
      pen.toLine
    }
    val edges = lines.map { line =>
      line.from.id ~> line.to.id
    }.toList
    Graph(edges: _*)
  }

  def getPenLines(topology: Topology) = {
    val pens = topology.data.pens
    pens.filter { pen =>
      pen.`type` == PenType.Line
    }
  }

  def getPenNodes(topology: Topology) = {
    val pens = topology.data.pens
    pens.filter { pen =>
      pen.`type` == PenType.Node && pen.id != "dataFileNode"
    }
  }

  def getFieldArrayNodes(topology: Topology) = {
    val pens = topology.data.pens
    pens.filter { pen =>
      pen.`type` == PenType.Node && pen.id != "dataFileNode" && pen.id != "preprocess_0"
    }
  }

  def getAllNodes(topology: Topology) = {
    val pens = topology.data.pens
    pens.filter { pen =>
      pen.`type` == PenType.Node
    }
  }

  def getFilesExistInfo(fileNames: js.Array[String]) = {
    val fileExistInfoUrl = g.jsRoutes.controllers.MissionController.getFileNamesExistInfo().url.toString
    val dict = js.Dictionary("fileNames" -> fileNames)
    val data = JSON.stringify(dict)
    Ajax.post(url = s"${fileExistInfoUrl}", data = data, headers = Map("Content-Type" -> "application/json")).map { xhr =>
      xhr.responseText.toJDB
    }
  }

  def refreshMissionInfo(missionId: String) = {
    val url = g.jsRoutes.controllers.WorkflowController.getMissionById().url.toString
    Ajax.get(url = s"${url.noCache}&missionId=${missionId}").map { xhr =>
      val dict = JSON.parse(xhr.responseText).toJDJAn
      val fileNames = dict("input").toJArS
      getFilesExistInfo(fileNames).map { infoDict =>
        dict.foreach { case (k, v) =>
          val trueV = k match {
            case "kind" => Tool.getWFKindA(v.toString).render
            case "state" => Tool.successA.render
            case "input" =>
              val vs = v.toJArS
              Tool.getInputByName("file").`val`(vs.head)
              if (vs.size > 1) {
                Tool.getInputByName("groupFile").`val`(vs(1))
              }
              vs.map { v =>
                if (infoDict(v)) {
                  val names = v.split("/")
                  val url = Tool.getDetailUrl(names(0))
                  a(href := s"${url}?fileName=${v}", target := "_blank", s"${v}")
                } else {
                  span(v)
                }
              }.mkString("&nbsp;&nbsp;")
            case x if x != "arg" => span(v.toString).render
          }
          $(s"#mission #${k}").html(trueV)
        }
      }
    }
  }

  def refreshCalculateConfig(f: JDJAn => Any = x => ()) = {
    val missionId = Tool.getMissionId
    if (missionId.nonEmpty) {
      val url = g.jsRoutes.controllers.WorkflowController.getConfigData().url.toString
      Ajax.get(url = s"${url.noCache}&missionId=${missionId}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
        val rs = xhr.responseText.toJDJAn
        Tool.fillByNames(rs.toJDS)
        $(".myFile").foreach { y =>
          val name = $(y).nameAttr
          $("#form").bv.revalidateField(name)
        }
        f(rs)
      }
    }
  }

}

object FeatureSelectionTool {

  var groups: List[String] = _
  var rowNames: List[String] = _
  var groupHeaders: List[String] = _

  def isMul = {
    groups.size > 2
  }

  def getKind(idStr: String = "") = {
    if (idStr.isEmpty) {
      ""
    } else {
      "workflow"
    }
  }

  def hideTab(parentJq: JQuery, tabIds: List[String]): Unit = {
    tabIds.foreach { tabId =>
      hideTab(parentJq, tabId)
    }
  }

  def showTab(parentJq: JQuery, tabIds: List[String]): Unit = {
    tabIds.foreach { tabId =>
      showTab(parentJq, tabId)
    }
  }

  def showTab(parentJq: JQuery, tabId: String) = {
    parentJq.find(s"a[href='#${tabId}']").parent("li").show()
  }

  def hideTab(parentJq: JQuery, tabId: String) = {
    parentJq.find(s"a[href='#${tabId}']").parent("li").siblingsWithSelf.removeClass("active")
    parentJq.find(s"a[href='#${tabId}']").parent("li").hide()
    val selectTabOp = parentJq.find(s"a[href='#${tabId}']").parent("li").siblings().mapElems(y => y).
      filter(x => $(x).isDisplay).
      map { y =>
        val href = $(y).find("a").attr("href").get
        href.replaceAll("#", "")
      }.filter { x =>
      x != s"${tabId}"
    }.headOption
    selectTabOp.foreach { selectTab =>
      parentJq.find(s"a[href='#${selectTab}']").parent("li").addClass("active")
      parentJq.find(s"#${selectTab}").siblings().removeClass("active in")
      parentJq.find(s"#${selectTab}").addClass("active in")
      selectArgTab(parentJq, s"${selectTab}Layout")
    }
  }

  def selectArgTab(parentJq: JQuery, tabId: String) = {
    parentJq.find(s"a[href='#${tabId}']").parent().siblings().removeClass("active")
    parentJq.find(s"a[href='#${tabId}']").parent("li").addClass("active")
    parentJq.find(s"#${tabId}").siblings().removeClass("active in")
    parentJq.find(s"#${tabId}").addClass("active in")
  }

  def getFinalFileName(idStr: String, fileName: String) = {
    if (idStr.isEmpty) {
      fileName
    } else {
      s"${idStr}/${fileName}"
    }
  }

  def resultShow(idStr: String) = {
    val kind = SharedTool.getKind(idStr)
    $(s".result.${kind}").show()
  }

  def getIdStr(y: Element) = {
    getIdStrJq(y).attr("id").get
  }

  def getIdStr(jq: JQuery) = {
    jq.parents(".myArg").attr("id").get
  }

  def getIdStrJq(y: Element) = {
    $(y).parents(".myArg")
  }

  def getFsData(rs: JDJAn) = {
    read[FsData](JSON.stringify(rs))
  }

}
